using Core.DataAccess.ApiJson;
using Core.DataAccess.ApiJson.Controllers;
using Core.DataAccess.ApiJson.SearchService;
using Core.Framework;
using DotNetty.Framework;
using DotNetty.Framework.BaseTriggers;
using iTool.Connector.CommandOfParameter;
using Grain.Interfaces;
using iTool.ClusterComponent;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;

namespace iTool.Connector.CommandWorkers
{
    /// <summary>
    /// 获取APIJSON数据
    /// </summary>
    public class APIJSONChannelWorker : WorkerController
    {
        private iToolClusterHostClient iCluster;
        private ISearchProvider searchProvider;
        private ILogger<APIJSONChannelWorker> logger;

        public APIJSONChannelWorker(iToolClusterHostClient cluster, ISearchProvider searchProvider, ILogger<APIJSONChannelWorker> logger)
        {
            this.iCluster = cluster;
            this.searchProvider = searchProvider;
            this.logger = logger;
        }

        [MethodRoute("iTool APIJSON")]
        public async Task<DoWorkResponse> APIJSON(HandleDoWorkingContext context)
        {
            object result = null;

            var parameter = context.Message.GetParameterModel<APIJSONParameter>();
            var iConfiguration = this.iCluster.GetService<IDatabaseConfigurationService>();
            var resultOfConnaction = await iConfiguration.GetConnactionByTitle(parameter.Connaction.Title);
            var sqlSugarClient = ApiJsonDbContext.CreateSqlSugarClient(resultOfConnaction.connationString);
            var selectTable = new SelectTable(sqlSugarClient, this.searchProvider, identity: context.Channel);
            var controller = new ApiJsonController(selectTable, this.searchProvider);


            switch (parameter.MothodType.ToLower())
            {
                // 查询
                case "get":
                    result = controller.Query(parameter.Script).ToString();
                    break;

                // 添加
                case "add":
                case "insert":
                case "register":
                    controller.SetTableSchema(await this.GetTableSchemaAsync(parameter.Connaction.Title, iConfiguration));
                    result = controller.Add(parameter.Script, out object trigger, out long id).ToString();
                    try
                    {
                        // 触发事件
                        if (trigger != null)
                        {
                            var channel = context.ChannelHandlerContext.GetChannel();
                            var function = this.iCluster.GetService<ICloudRunningFunctionService>(trigger.ToString());
                            await function.Invoke(channel, new object[] { id, parameter.Script });
                        }
                    }
                    catch (System.Exception ex)
                    {
                        this.logger.LogError(ex.Message);
                    }
                    break;

                // 修改
                case "modify":
                    controller.SetTableSchema(await this.GetTableSchemaAsync(parameter.Connaction.Title, iConfiguration));
                    result = controller.Edit(parameter.Script).ToString();
                    break;

                // 删除
                case "remove":
                    controller.SetTableSchema(await this.GetTableSchemaAsync(parameter.Connaction.Title, iConfiguration));
                    result = controller.Remove(parameter.Script).ToString();
                    break;
                default:
                    throw new System.Exception($"未知Action {parameter.MothodType} Hander");
            }

            return this.GetWorkResponse(context, result);
        }

        [MethodRoute("iTool DBSchema")]
        public async Task<DoWorkResponse> DBSchema(HandleDoWorkingContext context)
        {
            object result = 0;

            var parameter = context.Message.GetParameterModel<APIJSONParameter>();
            var iConfiguration = this.iCluster.GetService<IDatabaseConfigurationService>();

            var resultOfConnaction = await iConfiguration.GetConnactionByTitle(parameter.Connaction.Title, true);
            var sqlSugarClient = ApiJsonDbContext.CreateSqlSugarClient(resultOfConnaction.connationString);
            var databaseSchemaController = new DatabaseSchemaController(sqlSugarClient, this.searchProvider);

            switch (parameter.MothodType.ToLower())
            {
                // 还原数据库
                case "getschema":
                    var jSetting = new JsonSerializerSettings
                    {
                        NullValueHandling = NullValueHandling.Ignore,
                        DefaultValueHandling = DefaultValueHandling.Ignore
                    };
                    //result = JsonConvert.SerializeObject(resultOfConnaction.schema, jSetting);
                    result = resultOfConnaction.schema;
                    this.SetTableSchema(parameter.Connaction.Title, resultOfConnaction.schema);
                    break;

                // 还原数据库
                case "schema":
                    databaseSchemaController.RestoreDataBase(parameter.Connaction.Title, parameter.Script, async a =>
                    {
                        var iDatabaseConfiguration = this.iCluster.GetService<IDatabaseConfigurationService>();
                        await iDatabaseConfiguration.Modify(parameter.Connaction.Title, resultOfConnaction.connationString, a);
                    });
                    this.SetTableSchema(parameter.Connaction.Title, parameter.Script);
                    result = 1;
                    break;

                // 导出数据库
                case "export":
                    databaseSchemaController.ExportDataBaseToFile("./", parameter.Script);
                    result = 1;
                    break;

                default:
                    throw new System.Exception($"未知Action {parameter.MothodType} Hander");
            }

            return this.GetWorkResponse(context, result);
        }


        private void SetTableSchema(string title, string content)
        {
            string filePath = $"./{title}-tableSchema-new.json";
            File.WriteAllText(filePath, content);
        }

        private async Task<Dictionary<string, TableSchema>> GetTableSchemaAsync(string title, IDatabaseConfigurationService iConfiguration)
        {
            string filePath = $"./{title}-tableSchema-new.json";

            await this.IniTableSchemaAsync(title, iConfiguration);

            if (File.Exists(filePath))
            {
                return JsonConvert.DeserializeObject<Dictionary<string, TableSchema>>(File.ReadAllText(filePath)) ?? new Dictionary<string, TableSchema>();
            }
            else
            {
                return new Dictionary<string, TableSchema>();
            }
        }

        private async Task IniTableSchemaAsync(string title, IDatabaseConfigurationService iConfiguration)
        {
            string filePath = $"./{title}-tableSchema-new.json";
            if (!File.Exists(filePath))
            {
                var result = await iConfiguration.GetConnactionByTitle(title, true);
                this.SetTableSchema(title, result.schema);
            }
        }
    }
}
